home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MACD 5
/
MACD 5.bin
/
workbench
/
libs
/
newlooklib.lha
/
newlook
/
smartmem.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-12-26
|
14KB
|
678 lines
/*
* SMARTMEM.C
*
* (c)Copyright 1991-93 by Tobias Ferber, All Rights Reserved.
*/
#include <stdlib.h>
#include <exec/types.h>
#include <exec/memory.h>
/* exec.library prototypes */
extern void *AllocMem(ULONG,ULONG);
extern void FreeMem(void *,ULONG);
#include "newlook.h"
/*
* --- PRIVATE ---
*/
/****i* newlook.lib/--background-- ******************************************
*
* SMARTMEM
* smartmem.o offers some very useful functions concering
* memory management on Amiga systems.
* ... bla, bla, bla ...
*
* IDEAS
* SmartAllocRaster()
* SmartAllocMem(<bytesize>,<memory-type>)
*
* typedef struct memnode {
*
* struct memnode *succ,*pred;
* ULONG handle;
*
* union {
* APTR memory;
* PLANEPTR plane;
* } ptr;
*
* union {
* ULONG bytesize;
* struct {
* USHORT width,
* height;
* } dimen;
* } size;
*
* enum { RASTER,MEMORY } type; /* memtype attributes */
* } memnode_t;
*
******************************************************************************
*
*/
typedef struct memnode {
struct memnode *succ,
*pred;
ULONG handle;
void *memory;
ULONG bytesize;
} memnode_t;
#define NIL(type) (type)0L
static memnode_t *memlist= NIL(memnode_t *);
static ULONG current_handle= 0L;
/****i* newlook.lib/tail ******************************************
*
* NAME
* tail -- Return the last memnode pointer in a list
*
* SYNOPSIS
* t = tail( n )
*
* memnode_t *tail( memnode_t * );
*
* FUNCTION
* Traverse the list of memnodes linked to n->succ until
* n->succ is == NIL(menode_t *).
*
* INPUTS
* n - pointer to any memnode or NIL(memnode_t *)
*
* RESULT
* t - the last memnode or NIL(memnode_t *) if n was NIL(memnode_t *)
*
* SEE ALSO
* head()
*
******************************************************************************
*
*/
static memnode_t *tail(memnode_t *n)
{
return (n && n->succ) ? tail(n->succ) : n;
}
/****i* newlook.lib/head ******************************************
*
* NAME
* head -- Return the first memnode pointer in a list
*
* SYNOPSIS
* t = head( n )
*
* memnode_t *head( memnode_t * );
*
* FUNCTION
* Traverse the list of memnodes linked to n->pred until
* n->pred is == NIL(menode_t *).
*
* INPUTS
* n - pointer to any memnode or NIL(memnode_t *)
*
* RESULT
* t - the last memnode or NIL(memnode_t *) if n was NIL(memnode_t *)
*
* SEE ALSO
* tail()
*
******************************************************************************
*
*/
static memnode_t *head(memnode_t *n)
{
return (n && n->pred) ? head(n->pred) : n;
}
/****i* newlook.lib/addnode ******************************************
*
* NAME
* addnode -- Add a (list of) memnode(s) to the head of memlist
*
* SYNOPSIS
* addnode( n )
*
* void addnode( memnode_t * );
*
* FUNCTION
* Add memlist to the tail of n and make n the head of the new memlist
*
* INPUTS
* n - pointer to any memnode or NIL(memnode_t *)
*
* RESULT
* None.
*
* NOTES
* calling addnode( NIL(memnode_t *) ) is a no-op.
*
* SEE ALSO
* new()
*
******************************************************************************
*
*/
static void addnode(memnode_t *n)
{
register memnode_t *t;
if(t= tail(n))
{
if( t->succ= head(memlist) )
t->succ->pred= t;
memlist= head(n);
}
}
/****i* newlook.lib/new ******************************************
*
* NAME
* new -- Allocate and initialize a new memnode
*
* SYNOPSIS
* n= new()
*
* memnode_t *new( void );
*
* FUNCTION
* Allocate a new memnode using malloc() and initialize it.
* Especially the current handle will be copied to n->handle.
*
* INPUTS
* None.
*
* RESULT
* n - pointer to the new memnode or NIL(memnode_t *) on error.
*
* NOTES
* calling new() will not automatically chain the the new memnode
*
* SEE ALSO
* addnode()
*
******************************************************************************
*
*/
static memnode_t *new(void)
{
register memnode_t *n;
if(n= (memnode_t *)malloc(sizeof(memnode_t)))
{
n->succ=
n->pred= NIL(memnode_t *);
n->handle= current_handle;
n->memory= NIL(void *);
n->bytesize= 0UL;
}
return n;
}
/****i* newlook.lib/dispose ******************************************
*
* NAME
* dispose -- Unchain a memnode from memlist and free it
*
* SYNOPSIS
* dispose( n );
*
* void dispose( memnode_t * );
*
* FUNCTION
* Unchain n and keep memlist sane.
*
* INPUTS
* n - pointer to the memnode which is about to be disposed
*
* RESULT
* None.
*
* NOTES
* n->memory is _NOT_ freed by this function!
* If n is the last node in memlist then memlist is set to NIL.
*
* SEE ALSO
* new(), addnode()
*
******************************************************************************
*
*/
static void dispose(memnode_t *n)
{
if(n->pred == n->succ)
{ /* hacky: they _must_ be both NIL to be equal... */
memlist= NIL(memnode_t *);
}
else
{
if(n == memlist)
{
if(n->pred)
memlist= head(n->pred); /* should not happen */
else
memlist= n->succ;
}
if(n->pred)
n->pred->succ= n->succ;
if(n->succ)
n->succ->pred= n->pred;
n->pred=
n->succ= NIL(memnode_t *);
}
free(n);
}
/****i* newlook.lib/findnode ******************************************
*
* NAME
* findnode -- Find a memnode with memory at a certain location
*
* SYNOPSIS
* n = findnode( mem );
*
* memnode_t *findnode( void * );
*
* FUNCTION
* Scan memlist for a memnode which has memory allocated at given
* location "mem" with the current memory management handle.
*
* INPUTS
* mem - pointer to the memory returned by SmartAllocMem()
* or the macro SmartAllocate()
*
* RESULT
* n - the memnode with n->memory equal to mem and n->handle
* equal to the current_handle.
*
* SEE ALSO
* addnode()
*
******************************************************************************
*
*/
static memnode_t *findnode(void *mem)
{
register memnode_t *n= head(memlist);
/*for(n= head(memlist); n && n->memory != mem; n= n->succ) ;*/
while(n && n->memory != mem)
n= n->succ;
return (n && n->handle == current_handle) ? n : NIL(memnode_t *);
}
/*
* --- PUBLIC ---
*/
/****** newlook.lib/SetNewLookHandle ******************************************
*
* NAME
* SetNewLookHandle -- Set the current memory management handle
*
* SYNOPSIS
* lastHandle = SetNewLookHandle( newHandle )
*
* ULONG SetNewLookHandle( ULONG );
*
* FUNCTION
* Set the current memory management handle to newHandle and return
* the last handle.
*
* INPUTS
* newHandle - a unique number > 0 to identify your memory.
*
* RESULT
* lastHandle - the last handle.
*
* NOTES
* There are some reserved handles such as PRIVATE_HANDLE or
* MAGIC_HANDLE which you must not use here!
*
* SEE ALSO
* MakePrivateHandlePublic()
*
******************************************************************************
*
*/
ULONG SetNewLookHandle(ULONG new_handle)
{
register ULONG last_handle= current_handle;
current_handle= new_handle;
return last_handle;
}
/****** newlook.lib/SmartAllocMem ******************************************
*
* NAME
* SmartAllocMem -- Allocate and remember memory for a handle
*
* SYNOPSIS
* mem = SmartAllocMem( numbytes, attributes )
*
* void *SmartAllocMem( ULONG, ULONG );
*
* FUNCTION
* Allocate system memory via AllocMem() and chain it to the
* newlook memlist using the current memory management handle.
*
* INPUTS
* numbytes - The size of the desired block in bytes. (The
* operating system will automatically round this
* number to a multiple of the system memory chunk
* size.)
* attributes - requirements as explained in exec.library autodoc
* file and/or exec/memory.h
*
* RESULT
* mem - a pointer to the newly allocated memory block.
* If there are no free memory regions large enough to satisfy
* the request, zero will be returned. The pointer must be
* checked for zero before the memory block may be used!
* The memory block returned is long word aligned.
*
* SEE ALSO
* SetNewLookHandle(), SmartAllocate(), SmartFree(), SmartFreeAll()
* exec.library/AllocMem()
*
******************************************************************************
*
*/
void *SmartAllocMem(ULONG numbytes, ULONG attributes)
{
register memnode_t *n;
register void *mem= NIL(void *);
if(n= new())
{
if(mem= (void *)AllocMem(numbytes, attributes))
{
n->memory= mem;
n->bytesize= numbytes;
addnode(n);
}
else dispose(n);
}
return mem;
}
#ifdef OBSOLETE
/****** newlook.lib/SmartRemember ******************************************
*
* NAME
* SmartRemember -- Remember manually allocated memory (obsolete)
*
* SYNOPSIS
* success = SmartRemember( mem, numbytes )
*
* int SmartRemember( void *, ULONG );
*
* FUNCTION
* Chain given memory block "mem" to the newlook memlist using
* the current memory management handle.
*
* INPUTS
* mem - pointer to a memory block which has been
* allocated via AllocMem()
* numbytes - the size of the allocated memory block in
* bytes.
*
* RESULT
* success - 1 on success, 0 on error
*
* NOTES
* This function is declared obsolete and will be removed!
*
* SEE ALSO
* SmartAllocMem(), exec.library/AllocMem()
*
******************************************************************************
*
*/
int SmartRemember(void *mem, ULONG numbytes)
{
register memnode_t *n= NIL(memnode_t *);
if(mem && numbytes)
{
if(n= new())
{
n->memory= mem;
n->bytesize= numbytes;
addnode(n);
}
}
return n ? 1:0;
}
#endif /* OBSOLETE */
/****** newlook.lib/SmartFree ******************************************
*
* NAME
* SmartFree -- Free memory allocated via SmartAllocMem()
*
* SYNOPSIS
* nil = SmartFree( mem )
*
* void *SmartFree( void * );
*
* FUNCTION
* Free the memory block allocated via SmartAllocMem() and
* the current memory management handle.
*
* INPUTS
* mem - pointer to the memory block returned by SmartAllocMem()
*
* RESULT
* nil - a constant pointer to NIL(void *)
*
* NOTES
* If given pointer "mem" has never been returned by SmartAllocMem()
* or if it has already been freed up then calling this function is
* a no-op.
*
* SEE ALSO
* SmartAllocMem(), SmartFreeAll()
*
******************************************************************************
*
*/
void *SmartFree(void *mem)
{
register memnode_t *n;
if( n= findnode(mem) )
{
if(n->memory && n->bytesize)
FreeMem(mem,n->bytesize);
dispose(n);
}
return NIL(void *);
}
/****** newlook.lib/SmartFreeAll ******************************************
*
* NAME
* SmartFreeAll -- Free all memory allocated for a certain handle
*
* SYNOPSIS
* nil = SmartFreeAll( handle )
*
* void *SmartFreeAll( ULONG );
*
* FUNCTION
* Free all the memory which has been allocated via SmartAllocMem()
* for the given newlook handle.
*
* INPUTS
* handle - the handle to be freed or MAGIC_HANDLE for all handles
*
* RESULT
* nil - a constant pointer to NIL(void *)
*
* NOTES
* Calling SmartFreeAll( MAGIC_HANDLE ) will free all memory ever
* chained to the memlist.
*
* SEE ALSO
* SmartFree(), SmartAllocMem()
*
******************************************************************************
*
*/
void *SmartFreeAll(ULONG handle)
{
register memnode_t *n= head(memlist);
while(n)
{
register memnode_t *t= n;
n= n->succ;
if(t->handle == handle || handle == MAGIC_HANDLE)
{
if(t->memory && t->bytesize)
FreeMem(t->memory, t->bytesize);
dispose(t);
}
}
return NIL(void *);
}
#ifdef DEBUG
/****** newlook.lib/DebugSmartMemList ******************************************
*
* NAME
* DebugSmartMemList -- Print all memnodes in memlist
*
* SYNOPSIS
* DebugSmartMemList()
*
* void DebugSmartMemList( void );
*
* FUNCTION
* Traverse the memlist and print information about all nodes chained
* to it.
*
* NOTES
* This function is only available when comiled w/ -DDEBUG !
*
******************************************************************************
*
*/
void DebugSmartMemList(void)
{
register memnode_t *n= head(memlist);
if(n)
{
printf(" Handle | Memory | Bytesize\n"
"----------+----------+------------\n");
while(n)
{
printf("%9ld | 0x%06lX | %ld\n",n->handle,n->memory,n->bytesize);
n= n->succ;
}
}
else printf("%s: Memory list is empty.\n",__FILE__);
}
#endif /* DEBUG */
/*
* --- NewLook PRIVATE ---
*/
/****** newlook.lib/MakePrivateHandlePublic ******************************************
*
* NAME
* MakePrivateHandlePublic -- change memory handle from private to public
*
* SYNOPSIS
* MakePrivateHandlePublic( publicHandle )
*
* void MakePrivateHandlePublic( ULONG );
*
* FUNCTION
* Traverse the memlist and change all memnodes with a memory block
* allocated with the PRIVATE_HANDLE to the given publicHandle.
*
* INPUTS
* publicHandle - The new handle for the private memnodes.
*
* RESULT
* None.
*
* EXAMPLE
* Federal regulations prohibit a demonstration of this function.
*
* NOTES
* This function is newlook private and should not be called by the
* user!
*
* SEE ALSO
* SetNewLookHandle(), SmartAllocMem()
*
******************************************************************************
*
*/
void MakePrivateHandlePublic(ULONG public_handle)
{
if(public_handle != PRIVATE_HANDLE)
{
register memnode_t *n= head(memlist);
while(n)
{
if(n->handle == PRIVATE_HANDLE)
n->handle= public_handle;
n= n->succ;
}
}
current_handle= public_handle;
}